package cn.org.dian.easycommunicate.util;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

import android.os.Environment;

import com.google.api.translate.Language;

public class OnlineTTS {

    // private static final String TAG = "OnlineTTS";

    private static final String URL_BASE = "http://translate.google.com/translate_tts";

    private static final String AUDIO_CACHE_FOLDER_PREFIX = "/Android/data/cn.org.dian.easycommunicate/audio_cache";

    /**
     * Get the URL for online TTS
     * 
     * @param language
     * @param content
     * @return
     */
    public static String getURL(Language language, String content) {
        String realURL = "";
        realURL = URL_BASE + "?tl=" + language.toString() + "&q="
                + Utilities.utf8Encode(content);
        return realURL;

    }

    /**
     * cache dir:
     * /sdcard/Android/data/cn.org.dian.easycommunicate/audio_cache/en/XX.mp3 <br>
     * XX = speakText->utf-8 encode->BKDR Hash
     * 
     * @param searchFolder
     * @param cachedFileName
     * @return if cache file not found or SD card not available, return null
     */
    public static File getCachedAudioFile(Language language, String speakText) {

        if (!Utilities.checkSDCardUsability()) {
            return null;
        }

        File externalRoot = Environment.getExternalStorageDirectory();
        File audioCacheFolder = new File(externalRoot.getAbsolutePath()
                + AUDIO_CACHE_FOLDER_PREFIX + "/" + language.toString());

        if (!audioCacheFolder.exists()) {
            return null;
        }

        String legalFileName = Utilities.convertToLegalName(speakText);
        // if file name is too long, cache does not exist
        if (legalFileName.length() > Constants.FILE_NAME_LENGTH_MAX) {
            return null;
        }
        File cacheFile = new File(audioCacheFolder, legalFileName + ".mp3");
        if (cacheFile.exists()) {
            return cacheFile;
        } else {
            return null;
        }
    }

    /**
     * Make sure network is available and SD card is available before call
     * 
     * @param language
     * @param speakText
     * @return return the saved file. null if unsuccessful
     */
    public static File requestWebAndSaveToFile(Language language,
            String speakText) {

        // build dest file
        File externalRoot = Environment.getExternalStorageDirectory();
        File audioCacheFolder = new File(externalRoot.getAbsolutePath()
                + AUDIO_CACHE_FOLDER_PREFIX + "/" + language.toString());

        if (!audioCacheFolder.exists()) {
            audioCacheFolder.mkdirs();
        }

        String cacheFileName = Utilities.convertToLegalName(speakText) + ".mp3";

        File destFile = new File(audioCacheFolder, cacheFileName);

        // begin request web
        URL url = null;
        try {
            url = new URL(getURL(language, speakText));
        } catch (MalformedURLException e) {
            e.printStackTrace();
            return null;
        }
        // traffic stats
        NetworkTrafficStats.beginTrafficStats(false);

        HttpURLConnection httpURLConn = null;
        InputStream is = null;
        FileOutputStream fos = null;
        try {
            httpURLConn = (HttpURLConnection) url.openConnection();
            httpURLConn.setRequestMethod("GET");
            httpURLConn.setRequestProperty("Content-Type",
                    "text/xml; charset=UTF-8");
            httpURLConn.setRequestProperty("User-Agent", "Mozilla/5.0");
            httpURLConn.connect();
            is = httpURLConn.getInputStream();

            // open a local file input stream to accept the received data
            if (!destFile.exists()) {
                destFile.createNewFile();
            }
            fos = new FileOutputStream(destFile);

            // read bytes from net io and write to file io
            byte[] buffer = new byte[1024];
            int readNum = 0;
            while (-1 != (readNum = is.read(buffer))) {
                fos.write(buffer, 0, readNum);
            }
            return destFile;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            NetworkTrafficStats.endTrafficStats(false);
            try {
                if (fos != null) {
                    fos.close();
                    fos = null;
                }
                if (is != null) {
                    is.close();
                    is = null;
                }
                if (httpURLConn != null) {
                    httpURLConn.disconnect();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * clear the folder
     * /sdcard/Android/data/cn.org.dian.easycommunicate/audio_cache
     * 
     * @return true if success
     */
    public static boolean clearCache() {
        if (!Utilities.checkSDCardUsability()) {
            return false;
        }
        File externalRoot = Environment.getExternalStorageDirectory();
        File audioCacheFolder = new File(externalRoot.getAbsolutePath()
                + AUDIO_CACHE_FOLDER_PREFIX);
        if(!audioCacheFolder.exists()) {
            return false;
        }
        return deleteAll(audioCacheFolder);
    }
    
    /**
     * 
     * @return cache size in bytes <br>
     *          -1 if SD card not available
     */
    public static long getCacheSize() {
        if (!Utilities.checkSDCardUsability()) {
            return -1;
        }
        File externalRoot = Environment.getExternalStorageDirectory();
        File audioCacheFolder = new File(externalRoot.getAbsolutePath()
                + AUDIO_CACHE_FOLDER_PREFIX);
        if(!audioCacheFolder.exists()) {
            return 0;
        }
        return getSize(audioCacheFolder);
    }

    private static boolean deleteAll(File path) {
        if (!path.exists()) {
            return false;
        } else if (path.isFile()) {
            return path.delete();
        } else { // dir
            File[] files = path.listFiles();
            boolean finalResult = true;
            for (int i = 0; i < files.length; i++) {
                finalResult = finalResult && deleteAll(files[i]);
            }
            finalResult = finalResult && path.delete();
            return finalResult;
        }
        
    }
    
    private static long getSize(File path) {
        if (!path.exists()) {
            return 0;
        } else if (path.isFile()) {
            return path.length();
        } else { // is a dir
            File[] files = path.listFiles();
            long totalSize = 0;
            for (int i = 0; i < files.length; i++) {
                totalSize += getSize(files[i]);
            }
            return totalSize;
        }
    }

}
